x11: Avoid thawing surface until frame is drawn
authorRay Strode <rstrode@redhat.com>
Tue, 30 Jun 2020 18:15:53 +0000 (14:15 -0400)
committerRay Strode <rstrode@redhat.com>
Tue, 30 Jun 2020 18:36:15 +0000 (14:36 -0400)
Since commit 972134abe48a4c9c7b6ad41b0723f30f4e7ae16b a frame getting
drawn has three states (with the vendor nvidia driver at least):

1. drawn by gtk waiting on the GPU
2. drawn by GPU waiting on the compositor
3. drawn by compositor

Those three states are encoded in two flags: frame_pending and
frame_still_painting.

frame_pending means step 1 is done, but step 2 and 3 are still
in progress.  frame_still_painting means step 2 is still in progress.

After step 1 is finished the surface is frozen until step 3 is finished.

When the compositor notifies gtk it's done with step 3, with a
_NET_WM_FRAME_DRAWN client message, the toolkit thaws the surface to
allow the next frame to proceed.

The compositor sometimes sends gtk a _NET_WM_FRAME_DRAWN client message
between steps 1 and 2.  This message should be ignored because it's not
a reply to the current frame.

Unfortunately, gtk currently assumes if it gets a _NET_WM_FRAME_DRAWN
client message while waiting for step 2 that it's actually at step 3,
and proceeds to draw a new frame while the existing frame is still
pending, leading to a blown assertion.

This commit addresses the problem by ignoring _NET_WM_FRAME_DRAWN
client messages from the compositor unless actually expecting one.

Fixes: #2902
gdk/x11/gdkdisplay-x11.c

index 9804d0ea79648dfbf03077923c5dea7ce4615b01..ca337066b8fefc98f81acbed3cab8bc42c2202ed 100644 (file)
@@ -1184,7 +1184,7 @@ _gdk_wm_protocols_filter (const XEvent  *xevent,
           if (timings)
             timings->drawn_time = frame_drawn_time;
 
-          if (surface_impl->toplevel->frame_pending)
+          if (!surface_impl->toplevel->frame_still_painting && surface_impl->toplevel->frame_pending)
             {
               surface_impl->toplevel->frame_pending = FALSE;
               gdk_surface_thaw_updates (win);